package fun.codedesign.jdk.thread.juc;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 交替打印数字
 *
 * @author zengjian
 * @create 2018-04-16 10:31
 * @since 1.0.0
 */
public class ConditionTest {

    public static void main(String[] args) throws InterruptedException {
        PrintService printService = new PrintService();
        Thread thread1 = new PrintThread1(printService);
        Thread thread2 = new PrintThread2(printService);
        thread1.start();
        thread2.start();
    }

    private static class PrintService {
        private ReentrantLock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();
        private boolean flag = true; //轮流打印标志位
        private int count = 1; //打印数字的初始值

        public void print1() {
            // 先获得同步监视器，先打印为快
            try {
                while (count <= 10000) {
                    lock.lock();
                    if (flag == false) {
                        condition.await();
                    }
                    for (int i = 0; i < 3; i++) {
                        System.out.println(Thread.currentThread().getName() + ":" + count);
                        count++;
                    }
                    //打印完成了，就阻塞吧
                    // condition.signal(); //这个执行会不会有问题？
                    //把锁让出来，
                    flag = false;
                    // 将condition中的队列加到lock所在的队列，lock#unlock() 之后开始执行这个点。
                    condition.signal();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }

        public void print2() {
            try {
                while (count <= 10000) {
                    lock.lock();
                    if (flag == true) {
                        condition.await();
                    }
                    for (int i = 0; i < 3; i++) {
                        System.out.println(Thread.currentThread().getName() + ":" + count);
                        count++;
                    }
                    flag = true;
                    condition.signal();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }


    private static class PrintThread1 extends Thread {

        private PrintService service;

        public PrintThread1(PrintService service) {
            this.service = service;
        }

        @Override
        public void run() {
            service.print1();
        }
    }

    private static class PrintThread2 extends Thread {
        private PrintService service;

        public PrintThread2(PrintService service) {
            this.service = service;
        }

        @Override
        public void run() {
            service.print2();
        }
    }
}
